package com.deying.httplockserver.core;

import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.annotation.Resource;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import com.deying.httplockserver.utils.NettyHttpUtils;
import com.sun.org.apache.bcel.internal.util.ClassPath;

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.DefaultHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.QueryStringDecoder;
import io.netty.util.AttributeKey;

@Sharable
@Component
public class NettyHttpDispatcher extends ChannelInboundHandlerAdapter {
	@Resource
	WorkerManager workerManager;
	
	@Value("${lock.lockTime}")
	int defaultLockTime;
	
	@Value("${lock.waitTime}")
	int defaultWaitTime;
	
	/**chrome会发出ico请求，不处理很烦*/
	byte[] faviconData;
	
	public NettyHttpDispatcher() {
		InputStream ism = null;
		try {
			ism = new ClassPathResource("/favicon.ico").getInputStream();
			faviconData = IOUtils.toByteArray(ism);
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			IOUtils.closeQuietly(ism);
		}
	}
	

	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		if (msg instanceof DefaultHttpRequest) {
			try {
				DefaultHttpRequest request = (DefaultHttpRequest) msg;

				QueryStringDecoder queryStringDecoder = new QueryStringDecoder(request.uri());
				String path = queryStringDecoder.path();
				if("/lock".equals(path)){
					Map<String, List<String>> params = queryStringDecoder.parameters();
					String name = NettyHttpUtils.getParamString(params,"name");
					Assert.hasLength(name, "锁名不能为空");
					String tid = NettyHttpUtils.getParamString(params,"tid");
					Assert.hasLength(tid, "锁事务id不能为空");
					Integer lockTime = NettyHttpUtils.getParamInteger(params,"lockTime",defaultLockTime);
					Integer waitTime = NettyHttpUtils.getParamInteger(params,"waitTime",defaultWaitTime);
					HttpLockRequest httpLockRequest = new HttpLockRequest(ctx,name,tid,lockTime,waitTime);
					workerManager.lock(httpLockRequest);
				}else if("/tryLock".equals(path)){ //等同于lock的waitTime为0
					Map<String, List<String>> params = queryStringDecoder.parameters();
					String name = NettyHttpUtils.getParamString(params,"name");
					Assert.hasLength(name, "锁名不能为空");
					String tid = NettyHttpUtils.getParamString(params,"tid");
					Assert.hasLength(tid, "锁事务id不能为空");
					Integer lockTime = NettyHttpUtils.getParamInteger(params,"lockTime",defaultLockTime);
					HttpLockRequest httpLockRequest = new HttpLockRequest(ctx,name,tid,lockTime,0);
					workerManager.lock(httpLockRequest);
				}else if("/unLock".equals(path)){
					Map<String, List<String>> params = queryStringDecoder.parameters();
					String name = NettyHttpUtils.getParamString(params,"name");
					Assert.hasLength(name, "锁名不能为空");
					String tid = NettyHttpUtils.getParamString(params,"tid");
					Assert.hasLength(tid, "锁事务id不能为空");
					Boolean across = NettyHttpUtils.getParamBoolean(params,"across",false);
					HttpLockRelease httpLockRelease = new HttpLockRelease(ctx, name,tid,across);
					workerManager.unLock(httpLockRelease);
				}else if("/favicon.ico".equals(path)){
					FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.OK,Unpooled.wrappedBuffer(faviconData));
					response.headers().set(HttpHeaderNames.CONTENT_TYPE, "image/x-icon");
					response.headers().set(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
					response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderNames.KEEP_ALIVE);
					ctx.write(response);
					ctx.flush();
				}else{
					NettyHttpUtils.sendErrorUrl(ctx);
				}
			} catch (Exception e) {
				NettyHttpUtils.sendErrorMessage(ctx,e.getMessage());
			}

		}

	}

	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		ctx.flush();
	}

}
